from aiogram import Router, types, F
from aiogram.fsm.context import FSMContext
from loguru import logger as log

from database.models import Config
from tg_bot.filters.user_filter import IsAdmin
from tg_bot.keyboards import inline, callback_factory
from tg_bot.services.text import not_correct_input
from tg_bot.states.admin import AdminCmd, AdminConfig

SETTINGS_TEXT = 'Настройки бота: '


dp = Router()
dp.message.filter(IsAdmin(is_admin=True))
dp.callback_query.filter(IsAdmin())


async def admin_config_message(message: types.Message, state: FSMContext) -> None:
    """
    Конфиг бота.

    ----
    :param message: Сообщение тг.
    :param state: State.
    :return:
    """
    key = await inline.concatenate_key(
        await inline.admin_settings_menu(),
        await inline.back('admin_menu')
    )
    await message.answer(SETTINGS_TEXT, reply_markup=key)
    await state.set_state(AdminConfig.main)


@dp.callback_query(callback_factory.AdminMenuCall.filter(
    F.item == 'config'
), AdminCmd.main)
async def admin_config_call(call: types.CallbackQuery, state: FSMContext):
    """
    Переход к конфигурации бота по инлайн кнопке.

    ----
    :param call: Callback.
    :param state: State.
    :return:
    """
    key = await inline.concatenate_key(
        await inline.admin_settings_menu(),
        await inline.back('admin_menu')
    )
    try:
        await call.message.edit_text(SETTINGS_TEXT, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(SETTINGS_TEXT, reply_markup=key)
    await state.set_state(AdminConfig.main)


@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action.in_({'change_invite_bonus', 'change_ref_bonus', 'change_warns_count'})
), AdminConfig.main)
async def admin_config_change_values(call: types.CallbackQuery,
                                     state: FSMContext,
                                     callback_data: callback_factory.AdminActionCall):
    """
    Конфигурация бота по инлайн кнопкам.

    ----
    :param call: Callback.
    :param state: State.
    :param callback_data: Callback data.
    :return:
    """
    config = Config.objects.filter().first()
    match callback_data.action:
        case 'change_invite_bonus':
            text = f'Бонус за приглашение: {config.invite_bonus}\n\n' \
                   f'Введите новое значение либо жмите на кнопку'
            await state.set_state(AdminConfig.invite_bonus)
        case 'change_ref_bonus':
            text = f'Бонус за рефералов: {config.ref_bonus}\n\n' \
                   f'Введите новое значение либо жмите на кнопку'
            await state.set_state(AdminConfig.ref_bonus)
        case _:
            text = f'Лимит предупреждений: {config.warns}\n\n' \
                   f'Введите новое значение либо жмите на кнопку'
            await state.set_state(AdminConfig.warns)
    key = await inline.cancel()
    try:
        await call.message.edit_text(text, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(text, reply_markup=key)


@dp.message(AdminConfig.warns)
async def admin_config_set_warns(message: types.Message, state: FSMContext):
    """
    Настройка кол-ва предупреждений перед блокировкой.

    ----
    :param message: Сообщение.
    :param state: Состояние пользователя.
    :return:
    """
    config = Config.objects.filter().first()
    if message.text.isdigit():
        config.warns = int(message.text)
        config.save()
        await admin_config_message(message, state)
    else:
        await not_correct_input(message)


@dp.message(AdminConfig.invite_bonus)
@dp.message(AdminConfig.ref_bonus)
async def admin_config_set_new_values(message: types.Message, state: FSMContext):
    """
    Настройка бонусов реферальной программы.

    ----
    :param message: Сообщение.
    :param state: Состояние пользователя.
    :return:
    """
    try:
        float_value = float(message.text)
    except Exception as e:
        log.warning(e)
        return await not_correct_input(message)

    config = Config.objects.filter().first()
    match await state.get_state():
        case AdminConfig.invite_bonus:
            config.invite_bonus = float_value
        case AdminConfig.ref_bonus:
            config.ref_bonus = float_value
    config.save()
    await admin_config_message(message, state)


@dp.callback_query(callback_factory.ActionCall.filter(F.action == 'cancel'),
                   AdminConfig())
async def admin_config_cancel_set_new_value(call: types.CallbackQuery, state: FSMContext):
    """
    Отмена настройка конфигурации бота.

    ----
    :param call: Callback.
    :param state: State.
    :return:
    """
    await admin_config_call(call, state)
